package handler

/*
 +----------------------------------------------------------------------
 + Title        : UserHandler
 + Author       : huwl
 + Version      : 1.0.0
 + Initial-Time : 2018-01-06
 + Last-time    : 这个文件最后修改的时间 + 修改人的名称
 + Desc         : 用户处理器
 +----------------------------------------------------------------------
*/
import (
	"context"
	"math"
	"strings"
	"user-service/models"
	pbResult "user-service/proto/result"
	pbUser "user-service/proto/user"
	"user-service/tools"

	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
)

type UserHandler struct {
	pbUser.UnimplementedUserSrvServer
}

/**
 * 新增用户
 *
 * @param string Name -----------------------------------------非必传,姓名
 * @param string Nick -----------------------------------------非必传,昵称
 * @param string Email ----------------------------------------非必传,邮箱
 * @param string Username -------------------------------------非必传,用户名
 * @param string Password -------------------------------------非必传,密码
 * @param string AvatarUrl ------------------------------------非必传,头像
 * @param int Source ------------------------------------------非必传,来源
 * @param int Level -------------------------------------------非必传,级别
 * @param string Mobile ---------------------------------------非必传,手机号
 * @param int Gender ------------------------------------------非必传,性别
 * @param int ProvinceId --------------------------------------非必传,省Id
 * @param int CityId ------------------------------------------非必传,市Id
 * @param int DistrictId --------------------------------------非必传,区Id
 * @param int Score -------------------------------------------非必传,积分
 * @param int Balance -----------------------------------------非必传,余额
 * @param int Status ------------------------------------------非必传,状态
 * @param string Token ----------------------------------------非必传,token
 * @param string Note -----------------------------------------非必传,备注
 * @return *pbUser.AddUserResponse, error
 * @author huwl
 */
func (e *UserHandler) AddUser(ctx context.Context, req *pbUser.AddUserRequest) (*pbUser.AddUserResponse, error) {
	password := req.Password
	username := req.Username
	mobile := req.Mobile

	if username == "" {
		return nil, status.Errorf(codes.InvalidArgument, "用户名不能为空")
	}
	if !tools.CheckMobile(mobile) {
		return nil, status.Errorf(codes.InvalidArgument, "请输入正确格式的手机号")
	}

	//判断用户名是否重复
	var total int64
	err := models.User{}.GetTotalByParams(&models.User{}, &total, map[string]interface{}{
		"username":    username,
		"status <> ?": -2,
	})
	if err != nil || total > 0 {
		return nil, status.Errorf(codes.Aborted, "用户名已存在,请重新输入")
	}

	//判断手机号是否重复
	err = models.User{}.GetTotalByParams(&models.User{}, &total, map[string]interface{}{
		"mobile":      mobile,
		"status <> ?": -2,
	})
	if err != nil || total > 0 {
		return nil, status.Errorf(codes.Aborted, "手机号已存在,请重新输入")
	}

	bcryptPassword := ""
	if password != "" {
		bcryptPassword, _ = tools.Bcrypt(password)
	}

	user := models.User{
		Name:       req.Name,
		Nick:       req.Nick,
		Email:      req.Email,
		Username:   req.Username,
		Password:   bcryptPassword,
		AvatarUrl:  req.AvatarUrl,
		Source:     int(req.Source),
		Level:      int(req.Level),
		Mobile:     req.Mobile,
		Gender:     int(req.Gender),
		ProvinceId: int(req.ProvinceId),
		CityId:     int(req.CityId),
		DistrictId: int(req.DistrictId),
		Score:      int(req.Score),
		Balance:    int(req.Balance),
		Status:     int(req.Status),
		Token:      req.Token,
		Note:       req.Note,
	}
	i, err := models.User{}.Add(&user)
	if err != nil {
		return nil, err
	}
	if i <= 0 {
		return nil, status.Errorf(codes.Aborted, "新增用户失败")
	}

	return &pbUser.AddUserResponse{
		Code: 200,
		Msg:  "新增用户成功",
		User: &pbUser.User{
			Uid:        int64(user.Uid),
			Name:       user.Name,
			Nick:       user.Nick,
			Email:      user.Email,
			Username:   user.Username,
			Password:   bcryptPassword,
			AvatarUrl:  user.AvatarUrl,
			Source:     int64(user.Source),
			Level:      int64(user.Level),
			Mobile:     user.Mobile,
			Gender:     int64(user.Gender),
			ProvinceId: int64(user.ProvinceId),
			CityId:     int64(user.CityId),
			DistrictId: int64(user.DistrictId),
			Score:      int64(user.Score),
			Balance:    int64(user.Balance),
			Status:     int64(user.Status),
			Token:      user.Token,
			Note:       user.Note,
		},
	}, nil
}

/**
 * 用户列表
 *
 * @param int Uid ---------------------------------------------非必传,用户Id
 * @param string Uids -----------------------------------------非必传,用户Id多个
 * @param string Name -----------------------------------------非必传,姓名
 * @param string Nick -----------------------------------------非必传,昵称
 * @param string Email ----------------------------------------非必传,邮箱
 * @param string Username -------------------------------------非必传,用户名
 * @param int Source ------------------------------------------非必传,来源
 * @param int Level -------------------------------------------非必传,级别
 * @param string Mobile ---------------------------------------非必传,手机号
 * @param int Gender ------------------------------------------非必传,性别
 * @param int ProvinceId --------------------------------------非必传,省Id
 * @param int CityId ------------------------------------------非必传,市Id
 * @param int DistrictId --------------------------------------非必传,区Id
 * @param int Status ------------------------------------------非必传,状态
 * @param string StartCreateTime ------------------------------非必传,开始创建时间
 * @param string EndCreateTime --------------------------------非必传,结束创建时间
 * @param string SortField ------------------------------------非必传,排序字段
 * @param string SortType -------------------------------------非必传,排序方式
 * @param int PageSize ----------------------------------------非必传,条数
 * @param int Page --------------------------------------------非必传,页码
 * @return *pbUser.UserListResponse, error
 * @author huwl
 */
func (e *UserHandler) UserList(ctx context.Context, req *pbUser.QueryUserRequest) (*pbUser.UserListResponse, error) {
	params := map[string]interface{}{
		"status <> ?": -2,
	}

	page := req.Page
	pageSize := req.PageSize
	sortType := req.SortType
	sortField := req.SortField

	if req.Uid > 0 {
		params["uid"] = req.Uid
	}
	if req.Uids != "" {
		params["uid IN (?)"] = tools.IntSplit(strings.TrimRight(req.Uids, ","), ",")
	}
	if req.Name != "" {
		params["name"] = req.Name
	}
	if req.Nick != "" {
		params["nick"] = req.Nick
	}
	if req.Email != "" {
		params["email"] = req.Email
	}
	if req.Username != "" {
		params["username"] = req.Username
	}
	if req.Source > 0 {
		params["source"] = req.Source
	}
	if req.Level > 0 {
		params["level"] = req.Level
	}
	if req.Mobile != "" {
		params["mobile"] = req.Mobile
	}
	if req.Gender > 0 {
		params["gender"] = req.Gender
	}
	if req.ProvinceId > 0 {
		params["province_id"] = req.ProvinceId
	}
	if req.CityId > 0 {
		params["city_id"] = req.CityId
	}
	if req.DistrictId > 0 {
		params["district_id"] = req.DistrictId
	}
	if req.Status != "all" {
		params["status IN (?)"] = tools.IntSplit(req.Status, ",")
	}
	if req.StartCreateTime != "" {
		params["create_time >= ?"] = req.StartCreateTime + " 00:00:00"
	}
	if req.EndCreateTime != "" {
		params["create_time <= ?"] = req.EndCreateTime + " 23:59:59"
	}
	if page <= 0 {
		page = 1
	}
	if pageSize == 0 {
		pageSize = 20
	}
	if sortField == "" {
		sortField = "uid"
	}
	if sortType == "" {
		sortType = "desc"
	}

	var total int64
	err := models.User{}.GetTotalByParams(&models.User{}, &total, params)
	if err != nil {
		return nil, err
	}

	users := []*pbUser.User{}
	userItems := []models.User{}
	if total > 0 {
		err := models.User{}.GetResultsByParams(&models.User{}, &userItems, params, int(page), int(pageSize), sortField+" "+sortType)
		if err != nil {
			return nil, err
		}

		for _, user := range userItems {
			users = append(users, &pbUser.User{
				Uid:        int64(user.Uid),
				Name:       user.Name,
				Nick:       user.Nick,
				Email:      user.Email,
				Username:   user.Username,
				Password:   user.Password,
				AvatarUrl:  user.AvatarUrl,
				Source:     int64(user.Source),
				Level:      int64(user.Level),
				Mobile:     user.Mobile,
				Gender:     int64(user.Gender),
				ProvinceId: int64(user.ProvinceId),
				CityId:     int64(user.CityId),
				DistrictId: int64(user.DistrictId),
				Score:      int64(user.Score),
				Balance:    int64(user.Balance),
				Status:     int64(user.Status),
				Token:      user.Token,
				Note:       user.Note,
				CreateTime: user.CreateTime.Format("2006-01-02 15:04:05"),
				UpdateTime: user.UpdateTime.Format("2006-01-02 15:04:05"),
			})
		}
	}

	pageTotal := math.Ceil(float64(total) / float64(pageSize))

	return &pbUser.UserListResponse{
		ListResult: &pbResult.ListCommonResult{
			Page:      page,
			Total:     total,
			PageSize:  pageSize,
			PageTotal: int64(pageTotal),
		},
		Users: users,
	}, nil
}

/**
 * 用户数量
 *
 * @param int Uid ---------------------------------------------非必传,用户Id
 * @param string Uids -----------------------------------------非必传,用户Id多个
 * @param string Name -----------------------------------------非必传,姓名
 * @param string Nick -----------------------------------------非必传,昵称
 * @param string Email ----------------------------------------非必传,邮箱
 * @param string Username -------------------------------------非必传,用户名
 * @param int Source ------------------------------------------非必传,来源
 * @param int Level -------------------------------------------非必传,级别
 * @param string Mobile ---------------------------------------非必传,手机号
 * @param int Gender ------------------------------------------非必传,性别
 * @param int ProvinceId --------------------------------------非必传,省Id
 * @param int CityId ------------------------------------------非必传,市Id
 * @param int DistrictId --------------------------------------非必传,区Id
 * @param int Status ------------------------------------------非必传,状态
 * @param string StartCreateTime ------------------------------非必传,开始创建时间
 * @param string EndCreateTime --------------------------------非必传,结束创建时间
 * @param string SortField ------------------------------------非必传,排序字段
 * @param string SortType -------------------------------------非必传,排序方式
 * @param int PageSize ----------------------------------------非必传,条数
 * @param int Page --------------------------------------------非必传,页码
 * @return *pbUser.UserListResponse, error
 * @author huwl
 */
func (e *UserHandler) UserTotal(ctx context.Context, req *pbUser.QueryUserRequest) (*pbResult.TotalResult, error) {
	params := map[string]interface{}{
		"status <> ?": -2,
	}

	page := req.Page
	pageSize := req.PageSize
	sortType := req.SortType
	sortField := req.SortField

	if req.Uid > 0 {
		params["uid"] = req.Uid
	}
	if req.Uids != "" {
		params["uid IN (?)"] = tools.IntSplit(strings.TrimRight(req.Uids, ","), ",")
	}
	if req.Name != "" {
		params["name"] = req.Name
	}
	if req.Nick != "" {
		params["nick"] = req.Nick
	}
	if req.Email != "" {
		params["email"] = req.Email
	}
	if req.Username != "" {
		params["username"] = req.Username
	}
	if req.Source > 0 {
		params["source"] = req.Source
	}
	if req.Level > 0 {
		params["level"] = req.Level
	}
	if req.Mobile != "" {
		params["mobile"] = req.Mobile
	}
	if req.Gender > 0 {
		params["gender"] = req.Gender
	}
	if req.ProvinceId > 0 {
		params["province_id"] = req.ProvinceId
	}
	if req.CityId > 0 {
		params["city_id"] = req.CityId
	}
	if req.DistrictId > 0 {
		params["district_id"] = req.DistrictId
	}
	if req.Status != "all" {
		params["status IN (?)"] = tools.IntSplit(req.Status, ",")
	}
	if req.StartCreateTime != "" {
		params["create_time >= ?"] = req.StartCreateTime + " 00:00:00"
	}
	if req.EndCreateTime != "" {
		params["create_time <= ?"] = req.EndCreateTime + " 23:59:59"
	}
	if page <= 0 {
		page = 1
	}
	if pageSize == 0 {
		pageSize = 20
	}
	if sortType == "" {
		sortType = "uid"
	}
	if sortField == "" {
		sortType = "desc"
	}

	var total int64
	err := models.User{}.GetTotalByParams(&models.User{}, &total, params)
	if err != nil {
		return nil, err
	}
	return &pbResult.TotalResult{Total: total}, nil
}

/**
 * 获取单条用户信息
 *
 * @param string Name -----------------------------------------非必传,姓名
 * @param string Nick -----------------------------------------非必传,昵称
 * @param string Username -------------------------------------非必传,用户名
 * @param int Source ------------------------------------------非必传,来源
 * @param int Level -------------------------------------------非必传,级别
 * @param string Mobile ---------------------------------------非必传,手机号
 * @param int Gender ------------------------------------------非必传,性别
 * @param int ProvinceId --------------------------------------非必传,省ID
 * @param int CityId ------------------------------------------非必传,城市ID
 * @param int DistrictId --------------------------------------非必传,区ID
 * @param string Status ---------------------------------------非必传,状态支持多个：1,-1
 * @return User error
 * @author huwl
 */
func (e *UserHandler) Row(ctx context.Context, req *pbUser.QueryUserRequest) (*pbUser.UserResponse, error) {
	params := map[string]interface{}{
		"status <> ?": -2,
	}

	if req.Name != "" {
		params["name"] = req.Name
	}
	if req.Nick != "" {
		params["nick"] = req.Nick
	}
	if req.Email != "" {
		params["email"] = req.Email
	}
	if req.Username != "" {
		params["username"] = req.Username
	}
	if req.Source > 0 {
		params["source"] = req.Source
	}
	if req.Level > 0 {
		params["level"] = req.Level
	}
	if req.Mobile != "" {
		params["mobile"] = req.Mobile
	}
	if req.Gender > 0 {
		params["gender"] = req.Gender
	}
	if req.ProvinceId > 0 {
		params["province_id"] = req.ProvinceId
	}
	if req.CityId > 0 {
		params["city_id"] = req.CityId
	}
	if req.DistrictId > 0 {
		params["district_id"] = req.DistrictId
	}
	if req.Status != "all" {
		params["status IN (?)"] = tools.IntSplit(req.Status, ",")
	}

	user := models.User{}
	i, err := models.User{}.Row(&models.User{}, &user, params)
	if err != nil {
		return nil, err
	}
	if i <= 0 {
		return nil, status.Errorf(codes.Aborted, "用户信息错误")
	}

	return &pbUser.UserResponse{
		User: &pbUser.User{
			Uid:        int64(user.Uid),
			Name:       user.Name,
			Nick:       user.Nick,
			Email:      user.Email,
			Username:   user.Username,
			Password:   user.Password,
			AvatarUrl:  user.AvatarUrl,
			Source:     int64(user.Source),
			Level:      int64(user.Level),
			Mobile:     user.Mobile,
			Gender:     int64(user.Gender),
			ProvinceId: int64(user.ProvinceId),
			CityId:     int64(user.CityId),
			DistrictId: int64(user.DistrictId),
			Score:      int64(user.Score),
			Balance:    int64(user.Balance),
			Status:     int64(user.Status),
			Token:      user.Token,
			Note:       user.Note,
			CreateTime: user.CreateTime.Format("2006-01-02 15:04:05"),
			UpdateTime: user.UpdateTime.Format("2006-01-02 15:04:05"),
		},
	}, nil
}

/**
 * 用户详情
 *
 * @param int64 Uid -------------------------------------------必传,用户ID
 * @return *pbUser.UserResponse, error
 * @author huwl
 */
func (e *UserHandler) UserDetail(ctx context.Context, req *pbUser.UserDetailRequest) (*pbUser.UserResponse, error) {
	uid := req.Uid
	isHaveUserAlbum := req.IsHaveUserAlbum
	if uid <= 0 {
		return nil, status.Errorf(codes.InvalidArgument, "用户ID错误")
	}

	user := models.User{}
	i, err := models.User{}.GetResultByPrimaryKey(&user, uid, "uid")
	if err != nil {
		return nil, status.Errorf(codes.Aborted, err.Error())
	}
	if i <= 0 || user.Status == -2 {
		return nil, status.Errorf(codes.Aborted, "用户信息错误")
	}

	//获取用户相册
	userAlbums := []*pbUser.UserAlbum{}
	if isHaveUserAlbum == 1 {
		userAlbumItems := []models.UserAlbum{}
		err := models.UserAlbum{}.GetResultsByParams(&models.UserAlbum{}, &userAlbumItems, map[string]interface{}{
			"uid": uid,
		}, 1, -1, "id asc")
		if err != nil {
			return nil, status.Errorf(codes.Aborted, err.Error())
		}

		for _, userAlbumItem := range userAlbumItems {
			userAlbums = append(userAlbums, &pbUser.UserAlbum{
				Id:          int64(userAlbumItem.Id),
				Uid:         int64(userAlbumItem.Uid),
				ImageUrl:    userAlbumItem.ImageUrl,
				Description: userAlbumItem.Description,
				CreateTime:  userAlbumItem.CreateTime.Format("2006-01-02 15:04:05"),
				UpdateTime:  userAlbumItem.UpdateTime.Format("2006-01-02 15:04:05"),
			})
		}
	}
	return &pbUser.UserResponse{
		User: &pbUser.User{
			Uid:        int64(user.Uid),
			Name:       user.Name,
			Nick:       user.Nick,
			Email:      user.Email,
			Username:   user.Username,
			Password:   user.Password,
			AvatarUrl:  user.AvatarUrl,
			Source:     int64(user.Source),
			Level:      int64(user.Level),
			Mobile:     user.Mobile,
			Gender:     int64(user.Gender),
			ProvinceId: int64(user.ProvinceId),
			CityId:     int64(user.CityId),
			DistrictId: int64(user.DistrictId),
			Score:      int64(user.Score),
			Balance:    int64(user.Balance),
			Status:     int64(user.Status),
			Token:      user.Token,
			Note:       user.Note,
			CreateTime: user.CreateTime.Format("2006-01-02 15:04:05"),
			UpdateTime: user.UpdateTime.Format("2006-01-02 15:04:05"),
		},
		UserAlbums: userAlbums,
	}, nil
}
